package com.itmumu.chatgpt.session.defaults;

import cn.hutool.http.ContentType;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itmumu.chatgpt.IOpenAiApi;
import com.itmumu.chatgpt.billing.BillingUsage;
import com.itmumu.chatgpt.billing.Subscription;
import com.itmumu.chatgpt.domain.chat.ChatCompletionRequest;
import com.itmumu.chatgpt.domain.chat.ChatCompletionResponse;
import com.itmumu.chatgpt.domain.edits.EditRequest;
import com.itmumu.chatgpt.domain.edits.EditResponse;
import com.itmumu.chatgpt.domain.embedd.EmbeddingRequest;
import com.itmumu.chatgpt.domain.embedd.EmbeddingResponse;
import com.itmumu.chatgpt.domain.files.DeleteFileResponse;
import com.itmumu.chatgpt.domain.files.File;
import com.itmumu.chatgpt.domain.files.UploadFileResponse;
import com.itmumu.chatgpt.domain.images.ImageEditRequest;
import com.itmumu.chatgpt.domain.images.ImageRequest;
import com.itmumu.chatgpt.domain.images.ImageResponse;
import com.itmumu.chatgpt.domain.other.OpenAiResponse;
import com.itmumu.chatgpt.domain.qa.QACompletionRequest;
import com.itmumu.chatgpt.domain.qa.QACompletionResponse;
import com.itmumu.chatgpt.domain.whisper.TranscriptionsRequest;
import com.itmumu.chatgpt.domain.whisper.TranslationsRequest;
import com.itmumu.chatgpt.domain.whisper.WhisperResponse;
import com.itmumu.chatgpt.session.Configuration;
import com.itmumu.chatgpt.session.OpenAiSession;
import io.reactivex.Single;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSourceListener;

import java.time.LocalDate;
import java.util.List;

public class DefaultOpenAiSession implements OpenAiSession {
    /** 配置信息 */
    private final Configuration configuration;

    /** OpenAI 接口 */
    private final IOpenAiApi openAiApi;
    /** 工厂事件 */
    private final EventSource.Factory factory;

    public DefaultOpenAiSession(Configuration configuration) {
        this.configuration = configuration;
        this.openAiApi = configuration.getOpenAiApi();
        this.factory = configuration.createRequestFactory();
    }

    @Override
    public QACompletionResponse completions(QACompletionRequest qaCompletionRequest) {
        return this.openAiApi.completions(qaCompletionRequest).blockingGet();
    }

    @Override
    public QACompletionResponse completions(String question) {
        QACompletionRequest request = QACompletionRequest
                .builder()
                .prompt(question)
                .build();
        Single<QACompletionResponse> completions = this.openAiApi.completions(request);
        return completions.blockingGet();
    }

    @Override
    public EventSource completions(QACompletionRequest qaCompletionRequest, EventSourceListener eventSourceListener) throws JsonProcessingException {
        // 核心参数校验；不对用户的传参做更改，只返回错误信息。
        if (!qaCompletionRequest.isStream()){
            throw new RuntimeException("illegal parameter stream is false!");
        }

        // 构建请求信息
        Request request = new Request.Builder()
                .url(configuration.getApiHost().concat(IOpenAiApi.v1_completions))
                .post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), new ObjectMapper().writeValueAsString(qaCompletionRequest)))
                .build();

        // 返回事件结果
        return factory.newEventSource(request, eventSourceListener);
    }

    @Override
    public ChatCompletionResponse completions(ChatCompletionRequest chatCompletionRequest) {
        return this.openAiApi.completions(chatCompletionRequest).blockingGet();
    }

    @Override
    public EventSource chatCompletions(ChatCompletionRequest chatCompletionRequest, EventSourceListener eventSourceListener) throws JsonProcessingException {
        // 核心参数校验；不对用户的传参做更改，只返回错误信息。
        if (!chatCompletionRequest.isStream()) {
            throw new RuntimeException("illegal parameter stream is false!");
        }

        // 构建请求信息
        Request request = new Request.Builder()
                // url: https://api.openai.com/v1/chat/completions - 通过 IOpenAiApi 配置的 POST 接口，用这样的方式从统一的地方获取配置信息
                .url(configuration.getApiHost().concat(IOpenAiApi.v1_chat_completions))
                // 封装请求参数信息，如果使用了 Fastjson 也可以替换 ObjectMapper 转换对象
                .post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), new ObjectMapper().writeValueAsString(chatCompletionRequest)))
                .build();

        // 返回结果信息；EventSource 对象可以取消应答
        return factory.newEventSource(request, eventSourceListener);
    }

    // 新增方法
    @Override
    public EditResponse edit(EditRequest editRequest) {
        return null;
    }

    @Override
    public ImageResponse genImages(String prompt) {
        return null;
    }

    @Override
    public ImageResponse genImages(ImageRequest imageRequest) {
        return null;
    }

    @Override
    public ImageResponse editImages(File image, String prompt) {
        return null;
    }

    @Override
    public ImageResponse editImages(File image, ImageEditRequest imageEditRequest) {
        return null;
    }

    @Override
    public ImageResponse editImages(File image, File mask, ImageEditRequest imageEditRequest) {
        return null;
    }

    @Override
    public EmbeddingResponse embeddings(String input) {
        return null;
    }

    @Override
    public EmbeddingResponse embeddings(String... inputs) {
        return null;
    }

    @Override
    public EmbeddingResponse embeddings(List<String> inputs) {
        return null;
    }

    @Override
    public EmbeddingResponse embeddings(EmbeddingRequest embeddingRequest) {
        return null;
    }

    @Override
    public OpenAiResponse<File> files() {
        return null;
    }

    @Override
    public UploadFileResponse uploadFile(File file) {
        return null;
    }

    @Override
    public UploadFileResponse uploadFile(String purpose, File file) {
        return null;
    }

    @Override
    public DeleteFileResponse deleteFile(String fileId) {
        return null;
    }

    @Override
    public WhisperResponse speed2TextTranscriptions(File file, TranscriptionsRequest transcriptionsRequest) {
        return null;
    }

    @Override
    public WhisperResponse speed2TextTranslations(File file, TranslationsRequest translationsRequest) {
        return null;
    }

    @Override
    public Subscription subscription() {
        return null;
    }

    @Override
    public BillingUsage billingUsage(LocalDate starDate, LocalDate endDate) {
        return null;
    }
}
